﻿#include "function_create_shape_model.h"



void createMatchModel (HObject ho_image, HObject ho_roi, HObject ho_mask, HObject *ho_xld_show,
    HTuple *hv_Ret, HTuple *hv_Model)
{

  // Local iconic variables
  HObject  ho_maskRegion, ho_roi_mask, ho_ImageReduced;
  HObject  ho_ModelContours1;

  // Local control variables
  HTuple  hv_ModelRow, hv_ModelColumn, hv_ModelAngle;
  HTuple  hv_Score, hv_HomMat2D;

  Threshold(ho_mask, &ho_maskRegion, 50, 255);
  Difference(ho_roi, ho_maskRegion, &ho_roi_mask);
  ReduceDomain(ho_image, ho_roi_mask, &ho_ImageReduced);
  CreateShapeModel(ho_ImageReduced, "auto", -0.39, 0.79, "auto", "auto", "use_polarity",
      "auto", "auto", &(*hv_Model));
  GetShapeModelContours(&ho_ModelContours1, (*hv_Model), 1);
  FindShapeModel(ho_image, (*hv_Model),0, 6.29, 0.5, 1, 0.5, "least_squares",
      0, 0.9, &hv_ModelRow, &hv_ModelColumn, &hv_ModelAngle, &hv_Score);
  GetShapeModelContours(&(*ho_xld_show), (*hv_Model), 1);
  if (0 != (int((hv_Score.TupleLength())<0)))
  {
    (*hv_Ret) = -1;
    return;
  }
  VectorAngleToRigid(0, 0, 0, hv_ModelRow, hv_ModelColumn, hv_ModelAngle, &hv_HomMat2D);
  AffineTransContourXld((*ho_xld_show), &(*ho_xld_show), hv_HomMat2D);
  (*hv_Ret) = 1;

}

FunctionCreateShapeModel::FunctionCreateShapeModel(QDialog* parent,QString dir,QString section): QDialog(parent)
{
	m_dir = dir + "/" + section;
    m_qsettings = new QSettings(m_dir + "/para.ini", QSettings::IniFormat);

  

    this->setWindowTitle(("create model"));
    QRect desktop_rect = QApplication::desktop()->geometry();
    double ratio_x = desktop_rect.width()/1920.0;
    double ratio_y = desktop_rect.height()/1080.0;

    move(0,0);
    this->setFixedSize(1920*ratio_x,1010*ratio_y);

    QHBoxLayout* hlayout =new QHBoxLayout();
    this->setLayout(hlayout);



    QFrame* p = new QFrame(this);
    QSize control_size(240*ratio_x,40*ratio_y);
    p->setFrameShape(QFrame::WinPanel);
    p->move(0*ratio_x,0*ratio_y);
    p->setFixedSize(600*ratio_x,800*ratio_y);

    hlayout->addWidget(p);

    QGridLayout *qgridLayout = new QGridLayout();
    p->setLayout(qgridLayout);

    int index = 0;

    QSize ButtonSize(160 * ratio_x, 40 * ratio_y);



	m_pushbutton_show_orign_image = new QPushButton(this);
	m_pushbutton_show_orign_image->setFixedSize(control_size);
	m_pushbutton_show_orign_image->setText("Reload Current Image");
	connect(m_pushbutton_show_orign_image, &QPushButton::clicked, this, [=]() {
		m_image = m_image_current.clone();
		QImage q_image = matToQImage(m_image);
        m_view->setImage(q_image, "");
		return true;
	});
	qgridLayout->addWidget(m_pushbutton_show_orign_image, index, 0);
    index++;

	m_pushbutton_load_image = new QPushButton(this);
	m_pushbutton_load_image->setFixedSize(control_size);
	m_pushbutton_load_image->setText("Load Other Image");
	connect(m_pushbutton_load_image, &QPushButton::clicked, this, [=]() {
		QString filename;
		filename = QFileDialog::getOpenFileName(this,
			tr("select image"),
			"",
			tr("Images (*.png *.bmp *.jpg)"));
		if (filename.isEmpty())
		{
			return;
		}

		m_image = imread(filename.toLocal8Bit().toStdString(), IMREAD_UNCHANGED);

		if (m_image.empty())
		{
			QMessageBox::information(nullptr, "", "load image error");
			return;
		}


		QImage q_image = matToQImage(m_image);
		m_view->setImage(q_image, "");
		return ;
	});
	qgridLayout->addWidget(m_pushbutton_load_image, index, 0);
	index++;

	m_pushbutton_load_image = new QPushButton(this);
	m_pushbutton_load_image->setText("Load One Image");
	m_pushbutton_load_image->setFixedSize(control_size);
	connect(m_pushbutton_load_image, &QPushButton::clicked, this, [=]() {
		QString filename;
		filename = QFileDialog::getOpenFileName(this,
			tr("select image"),
			"",
			tr("Images (*.png *.bmp *.jpg)"));
		if (filename.isEmpty())
		{
			return;
		}
		m_image = imread(filename.toLocal8Bit().toStdString(), IMREAD_UNCHANGED);
		if (m_image.empty())
		{
			QMessageBox::information(nullptr, "", "load image error");
			return;
		}


		QImage q_image = matToQImage(m_image);
		m_view->setImage(q_image, "");
	});
	qgridLayout->addWidget(m_pushbutton_load_image, index, 0);
	index++;

	

   

	m_pushbutton_detection = new QPushButton(this);
	m_pushbutton_detection->setFixedSize(control_size);
	m_pushbutton_detection->setText("Create Model");
	connect(m_pushbutton_detection, &QPushButton::clicked, this, &FunctionCreateShapeModel::detectionImage);
	qgridLayout->addWidget(m_pushbutton_detection, index, 0);
	index++;

	m_pushbutton_save_parameter = new QPushButton(this);
	m_pushbutton_save_parameter->setFixedSize(control_size);
	m_pushbutton_save_parameter->setText("Save");
	connect(m_pushbutton_save_parameter, &QPushButton::clicked, this, &FunctionCreateShapeModel::saveParameter);
	qgridLayout->addWidget(m_pushbutton_save_parameter, index, 0);
	index++;

    m_pushbutton_return = new QPushButton(this);
    m_pushbutton_return->setFixedSize(control_size);
    m_pushbutton_return->setText("Exit");
    qgridLayout->addWidget(m_pushbutton_return, index, 0);
    connect(m_pushbutton_return, &QPushButton::clicked, this, [=]() {
        this->hide();
        });



    QVBoxLayout* view_layout =new QVBoxLayout();
    view_layout->setMargin(0);
    QSize view_controlsize(100*ratio_x,40*ratio_y);


    QHBoxLayout* view_tool_layout =new QHBoxLayout();

    QPushButton* p_QPushButton = new QPushButton(this);
    p_QPushButton->setFixedSize(view_controlsize);
    p_QPushButton->setText("Draw ROI");
    connect(p_QPushButton, &QPushButton::clicked, this,  [=]() {
		m_view->m_pixmapItem->setShapeType(1);
		m_view->m_pixmapItem->setColor(Qt::blue);
		m_view->m_pixmapItem->setFilled(false);
    });
    view_tool_layout->addWidget(p_QPushButton);

    p_QPushButton = new QPushButton(this);
    p_QPushButton->setFixedSize(view_controlsize);
    p_QPushButton->setText("Delete ROI");
    view_tool_layout->addWidget(p_QPushButton);
    connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
                    for (GraphicsShapeRectangleCirce *item : m_vector_graphics_shape_rectangle) {
                        m_view->scene()->removeItem(item);
                        delete item;
                    }
                    m_vector_graphics_shape_rectangle.clear();
        });

    p_QPushButton = new QPushButton(this);
    p_QPushButton->setFixedSize(view_controlsize);
    p_QPushButton->setText("Draw Mask");
    connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
		m_view->m_pixmapItem->setShapeType(3);
		m_view->m_pixmapItem->setColor(Qt::red);
		m_view->m_pixmapItem->setFilled(false);
        for (GraphicsShapeRectangleCirce *item : m_vector_graphics_shape_rectangle) {
            item->setOpacity(0);
        }

    });
    view_tool_layout->addWidget(p_QPushButton);

	p_QPushButton = new QPushButton(this);
	p_QPushButton->setFixedSize(view_controlsize);
	p_QPushButton->setText("Delete Mask");
	connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
		m_view->m_pixmapItem->setShapeType(4);
		m_view->m_pixmapItem->setColor(Qt::blue);
		m_view->m_pixmapItem->setFilled(false);
		for (GraphicsShapeRectangleCirce *item : m_vector_graphics_shape_rectangle) {
			item->setOpacity(0);
		}

	});
	view_tool_layout->addWidget(p_QPushButton);

    QLabel* pQLabel = new QLabel();
    pQLabel->setText("Pen Width");
    pQLabel->setFixedSize(view_controlsize);
    view_tool_layout->addWidget(pQLabel);

    QSlider* qslider_line_width = new QSlider(Qt::Horizontal,this);
    qslider_line_width->setFixedSize(400*ratio_x,20*ratio_y);
    qslider_line_width->setTickPosition(QSlider::NoTicks);
    qslider_line_width->setSingleStep(1);
    qslider_line_width->setMinimum(1);
    qslider_line_width->setMaximum(30);
    connect(qslider_line_width, &QSlider::valueChanged, this, [=](int value) {
        m_view->m_pixmapItem->setPenWidth(value);
        m_view->m_pixmapItem->update();
    });
    view_tool_layout->addWidget(qslider_line_width);

	/*p_QPushButton = new QPushButton(this);
	p_QPushButton->setFixedSize(view_controlsize);
	p_QPushButton->setText("Back Mask");
	view_tool_layout->addWidget(p_QPushButton);
	connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
		m_view->m_pixmapItem->backMask();
	});*/

    p_QPushButton = new QPushButton(this);
    p_QPushButton->setFixedSize(view_controlsize);
    p_QPushButton->setText("Clear Mask");
    view_tool_layout->addWidget(p_QPushButton);
    connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
            m_view->m_pixmapItem->clearMask();
        });

  /*  p_QPushButton = new QPushButton(this);
    p_QPushButton->setFixedSize(view_controlsize);
    p_QPushButton->setText("导出屏蔽图");
    view_tool_layout->addWidget(p_QPushButton);
    connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
            QImage qimage = m_view->m_pixmapItem->m_qpixmap_mask->toImage().convertToFormat(QImage::Format_Grayscale8);
            int width = qimage.width();
                int height = qimage.height();
            HObject hobject_mask;
            GenImage1(&hobject_mask, "byte", width, height, (Hlong)qimage.bits());

            qimage.save("mask.png", "PNG");
        });
*/

//    p_QPushButton = new QPushButton(this);
//    p_QPushButton->setFixedSize(view_controlsize);
//    p_QPushButton->setText("rect");
//    connect(p_QPushButton, &QPushButton::clicked, this,  [=]() {
//       m_view->m_pixmapItem->m_shape_type =1;
//       m_view->m_pixmapItem->m_color = Qt::darkYellow;
//       m_view->m_pixmapItem->m_bool_filled=true;
//    });
//    view_tool_layout->addWidget(p_QPushButton);


//    p_QPushButton = new QPushButton(this);
//    p_QPushButton->setFixedSize(view_controlsize);
//    p_QPushButton->setText("circle");
//    connect(p_QPushButton, &QPushButton::clicked, this,  [=]() {
//       m_view->m_pixmapItem->m_shape_type =2;
//       m_view->m_pixmapItem->m_color = Qt::darkYellow;
//       m_view->m_pixmapItem->m_bool_filled=true;
//    });
//    view_tool_layout->addWidget(p_QPushButton);

    view_layout->addLayout(view_tool_layout);

    m_view = new QtQGraphicsView(this);
    m_view->setFixedSize(1250 * ratio_x, 900 * ratio_y);


    connect(m_view->m_pixmapItem, &QtQGraphicsPixmapItem::sendMessage, this,[=](QPointF pos,QString message)
    {
        Q_UNUSED(pos);
        m_view_pixel_qlabel->setText(message);
    });

    connect(m_view->m_pixmapItem, &QtQGraphicsPixmapItem::drawRectangleFinish, this,[=](QGraphicsItem* p,int draw_type)
    {
        if(draw_type==1)
            m_vector_graphics_shape_rectangle.push_back((GraphicsShapeRectangleCirce*)p);
    });

    connect(m_view->m_pixmapItem, &QtQGraphicsPixmapItem::drawEraseFinish, this,[=]()
    {
        for (GraphicsShapeRectangleCirce *item : m_vector_graphics_shape_rectangle) {

            item->setOpacity(1);
        }
    });
    view_layout->addWidget(m_view);


    m_view_pixel_qlabel = new QLabel(this);
    m_view_pixel_qlabel->setAlignment(Qt::AlignRight );
    m_view_pixel_qlabel->setText("");
    m_view_pixel_qlabel->setFixedSize(1250 * ratio_x, 20 * ratio_y);
    view_layout->addWidget(m_view_pixel_qlabel);
    hlayout->addLayout(view_layout);

    loadParameter();
}

FunctionCreateShapeModel::~FunctionCreateShapeModel()
{
    ;
}

bool FunctionCreateShapeModel::detection( HObject image_in, QString& message)
{
    try
    {
        HObject roi;
		GenEmptyObj(&roi);
        for(int i=0;i<m_vector_graphics_shape_rectangle.size();i++)
        {
            HObject obj;
            QRectF qrectf = m_vector_graphics_shape_rectangle[i]->returnRect();
            int row1 = m_vector_graphics_shape_rectangle[i]->pos().y() + (int)qrectf.y();
            int column1 = m_vector_graphics_shape_rectangle[i]->pos().x() + (int)qrectf.x();
            int row2 = m_vector_graphics_shape_rectangle[i]->pos().y() + (int)(qrectf.y() + qrectf.height());
            int column2 = m_vector_graphics_shape_rectangle[i]->pos().x() + (int)(qrectf.x() + qrectf.width());
            GenRectangle1(&obj, row1, column1, row2, column2);
            Union2(roi,obj,&roi);
        }

		m_qimage_mask = m_view->m_pixmapItem->m_qpixmap_mask->toImage();
        QImage image_mask = m_qimage_mask.convertToFormat(QImage::Format_Grayscale8);
        int width = m_qimage_mask.width();
        int height = m_qimage_mask.height();
        HObject hobject_mask;
        GenImage1(&hobject_mask, "byte", width, height, (Hlong)image_mask.bits());



        HTuple hv_max_value, hv_ret;
        createMatchModel(image_in,roi,hobject_mask,&m_xld_show,&hv_ret,&m_model_match);


        int ret = hv_ret[0].I();
		
        if(ret>0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
	catch (HException &HDevExpDefaultException)
	{
		message = HDevExpDefaultException.ErrorMessage();
		return false;
	}
  
    return true;
}

void FunctionCreateShapeModel::detectionImage()
{
    if(m_image.empty())
    {
        QMessageBox::information(nullptr,"","no image");
        return;
    }

    QString message;
    HObject image = matToHImage(m_image);
    bool state = detection(image, message);


    if(!state)
    {
        QMessageBox::information(nullptr,"","create model error");
        return;
    }
    Mat image_show = m_image.clone();
    draw(image_show, image_show);

    QImage q_image = matToQImage(image_show);

    m_view->setImage(q_image, message);
    
    }

void FunctionCreateShapeModel::draw(Mat image_in,Mat& image_out)
{
    if(image_in.empty())
    {
        return;
    }
	if (image_in.channels() == 1)
	{
		cvtColor(image_in, image_in, COLOR_GRAY2BGR);
	}


    image_out = drawXld(image_in, m_xld_show, Scalar(0, 255, 0));
    GenEmptyRegion(&m_xld_show);
}

void FunctionCreateShapeModel::loadParameter()
{
    int roi_number = m_qsettings->value(m_section + "/" + "roi_number",0).toInt();
    for(int i=0;i<roi_number;i++)
    {
        int row1    = m_qsettings->value(m_section + "/" + "ROI" + QString::number(i)+"row1", 100).toInt();
        int column1 = m_qsettings->value(m_section + "/" + "ROI" + QString::number(i)+"column1", 100).toInt();
        int row2    = m_qsettings->value(m_section + "/" + "ROI" + QString::number(i)+"row2", 200).toInt();
        int column2 = m_qsettings->value(m_section + "/" + "ROI" + QString::number(i)+"column2", 200).toInt();

        GraphicsShapeRectangleCirce* p = new GraphicsShapeRectangleCirce( column1, row1,column2-column1,row2-row1,Qt::blue);
        m_view->m_scene->addItem(p);
        p->setZValue(101);
        m_vector_graphics_shape_rectangle.push_back(p);
    }

    m_qimage_mask.load((m_dir + "/mask.png").toLocal8Bit().toStdString().c_str());

    try{
        ReadShapeModel((m_dir + "/model.shm").toLocal8Bit().toStdString().c_str(),&m_model_match);
    }
    catch (HException &HDevExpDefaultException){
        QString message = HDevExpDefaultException.ErrorMessage().Text();
//        QMessageBox::information(nullptr,"",message);
        return;
    }
	m_image_model = imread((m_dir + "/image.png").toLocal8Bit().toStdString(),-1);
    return ;
}

void FunctionCreateShapeModel::saveParameter()
{
    m_qsettings->setValue(m_section + "/" + "roi_number", m_vector_graphics_shape_rectangle.size());
    for(int i=0;i<m_vector_graphics_shape_rectangle.size();i++)
    {
        QRectF qrectf = m_vector_graphics_shape_rectangle[i]->returnRect();
        int row1 = m_vector_graphics_shape_rectangle[i]->pos().y() + (int)qrectf.y();
        int column1 = m_vector_graphics_shape_rectangle[i]->pos().x() + (int)qrectf.x();
        int row2 = m_vector_graphics_shape_rectangle[i]->pos().y() + (int)(qrectf.y() + qrectf.height());
        int column2 = m_vector_graphics_shape_rectangle[i]->pos().x() + (int)(qrectf.x() + qrectf.width());
        m_qsettings->setValue(m_section + "/" + "ROI" + QString::number(i)+"row1", row1);
        m_qsettings->setValue(m_section + "/" + "ROI" + QString::number(i)+"column1", column1);
        m_qsettings->setValue(m_section + "/" + "ROI" + QString::number(i)+"row2", row2);
        m_qsettings->setValue(m_section + "/" + "ROI" + QString::number(i)+"column2", column2);
    }

    if (!QDir().exists(m_dir))
    {
        QDir().mkpath(m_dir);
    }


    m_qimage_mask.save((m_dir + "/mask.png").toLocal8Bit().toStdString().c_str(), "PNG");

    if(m_image.empty())
    {
        QMessageBox::information(nullptr,"","no image");
        return;
    }
	m_image_model = m_image;
    imwrite((m_dir + "/image.png").toLocal8Bit().toStdString(), m_image_model);

    try{
        if(m_model_match.Length()==0)
        {
            QMessageBox::information(nullptr,"","no model");
            return;
        }
        WriteShapeModel(m_model_match,(m_dir + "/model.shm").toLocal8Bit().toStdString().c_str());
    }
    catch (HException &HDevExpDefaultException){
        QString message = HDevExpDefaultException.ErrorMessage().Text();
        QMessageBox::information(nullptr,"",message);
        return;
    }
    return;
}

bool FunctionCreateShapeModel::showNew()
{
    QImage q_image = matToQImage(m_image);
    m_view->setImage(q_image, "");
	this->show();
    return true;
}

bool FunctionCreateShapeModel::showEdit()
{
	m_image = m_image_model.clone();
	QImage q_image = matToQImage(m_image);
	m_view->setImage(q_image, "");

	m_view->m_pixmapItem->setMask(m_qimage_mask);
	this->show();
	return true;
}


